package com.powergisol.gis.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.metadata.Sheet;
import com.powergisol.gis.dao.TabDataSettingMapper;
import com.powergisol.gis.dao.TabMouldMapper;
import com.powergisol.gis.dao.TabWall1Mapper;
import com.powergisol.gis.dto.ExcelTabWall1DTO;
import com.powergisol.gis.entity.TabCoordinateSystem;
import com.powergisol.gis.entity.TabWall1;
import com.powergisol.gis.listener.TabWall1Listener;
import com.powergisol.gis.service.TabWallService;
import com.powergisol.gis.util.FileUpload;
import com.powergisol.gis.util.FileUtil;
import com.powergisol.gis.util.Result;
import com.powergisol.gis.util.ZipUtil;
import com.powergisol.gis.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author : laishihao
 * @date : 2020/11/12
 * description :
 */
@Service
public class TabWallServiceImpl implements TabWallService {

    @Value("${earth-url}")
    private String earthUrl;
    @Resource
    private TabMouldMapper tabMouldMapper;


    @Resource
    private CacheManager cacheManager;
    @Autowired
    private TabDataSettingMapper tabDataSettingMapper;

    @Autowired
    private TabWall1Mapper tabWall1Mapper;


    /**
     * 缓存数据检查线程池大小核心线程数
     */
    private static final int DEVICE_DATA_DISPOSE_THREAD_CORE_POOL_SIZE = 5;
    /**
     * 缓存数据检查线程池大小最大并发数
     */
    private static final int DEVICE_DATA_DISPOSE_THREAD_MAXIMUM_POOL_SIZE = 40;
    /**
     * 数据处理线程池最大待处理任务量
     */
    private static final int MAX_WAIT_TASK_COUNT = 5000;
    private static ThreadPoolExecutor excelDataDisposeThreadPool;

    static {
        excelDataDisposeThreadPool = new ThreadPoolExecutor(DEVICE_DATA_DISPOSE_THREAD_CORE_POOL_SIZE,
                DEVICE_DATA_DISPOSE_THREAD_MAXIMUM_POOL_SIZE,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(MAX_WAIT_TASK_COUNT), r -> {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        });
    }


    @Override
    public Result wall1Import(MultipartFile excelFile, TabWall1VO vo, TabUserVo user) {
        Result result = new Result();
        Map<String,Object> map = new HashMap<>();
        Integer serviceId = null;
        try {

            String uuid = vo.getUuid();
            String userDir = System.getProperty("user.dir");

            //上传文件
            result = FileUpload.fileUpload(excelFile, userDir, uuid);
            userDir = (String) result.getData();

            String fileName1 = excelFile.getName();
            vo.setFileName(fileName1);
            // 获取文件名
            String fileName = excelFile.getOriginalFilename();
            // 获取文件的后缀名
            vo.setFileName(fileName.substring(0, fileName.lastIndexOf(".")));

            //发布服务
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss");
            String serviceName = vo.getFileName() + sdf1.format(new Date());
            TabServiceVo tabServiceVo = new TabServiceVo();
            tabServiceVo.setServiceUrl(earthUrl + serviceName);
            //根据用户查询用户
            tabServiceVo.setUserId(user.getId());

            tabServiceVo.setName(serviceName);
            tabServiceVo.setReleaseTime(new Date());
            tabServiceVo.setServiceType(22);
            tabServiceVo.setUuid(vo.getUuid());
            //保存服务
            tabDataSettingMapper.saveService(tabServiceVo);
            tabDataSettingMapper.saveUserService(tabServiceVo.getUserId(), tabServiceVo.getId());


            TabCoordinateSystem system = new TabCoordinateSystem();
            if (1 == vo.getIsChange()) {
                system = tabMouldMapper.getCoorByName(vo.getCoorName());
            }
            //保存入库
            //解压文件
            String zipUrl = userDir.substring(0, userDir.lastIndexOf(File.separator)) + File.separator + uuid;
            ZipUtil.unZip(userDir, zipUrl);


            ExcelTabWall1DTO tabWallDTO = new ExcelTabWall1DTO();

            List<File> listFile = FileUtil.recursionFile(zipUrl, null);
            ExcelReader excelReader = null;

            Cache cache = cacheManager.getCache("cache-data");
            //成功条数
            AtomicInteger cgNum = new AtomicInteger();
            //失败数据
            List<ExcelInFailedDataVo> listFailed = new ArrayList<>();
            List<Future<?>> taskList = new ArrayList<>();
            for (File file : listFile) {
                String excelName = file.getName();
                excelReader = EasyExcel.read(file).build();
                List<Sheet> sheets = excelReader.getSheets();
                TabCoordinateSystem finalSystem = system;
                Future<?> task = excelDataDisposeThreadPool.submit(() -> {
                    try {
                        for (Sheet sheet : sheets) {
                            TabWall1VO vo1 = new TabWall1VO();
                            String sheetName = sheet.getSheetName();
                            BeanUtils.copyProperties(vo, vo1);
                            // vo1.setHcdm01(excelName);
                            vo1.setExcelName(excelName);
                            vo1.setSheetName(sheetName);
                            String beforeSheetName = sheet.getSheetName().substring(0, 2);
                            if (beforeSheetName.equals("Sh") || beforeSheetName.equals("LB")) {
                                continue;
                            } else {
                                TabWall1Listener listener = new TabWall1Listener(vo1, finalSystem,
                                        cacheManager, tabWallDTO);
                                EasyExcelFactory.readBySax(new FileInputStream(file.getAbsolutePath()), sheet, listener);
                                if(null != cache.get(sheetName+uuid +"sb")){
                                    TaskResultVo taskResultVo = cache.get(sheetName+uuid +"sb",TaskResultVo.class);
                                    listFailed.addAll(taskResultVo.getListFailed());
                                }else{
                                    cgNum.set(cgNum.get() + 1);
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                taskList.add(task);
            }
            waitTaskListCompleted(taskList);
            //持久化excel数据
            LinkedBlockingDeque<TabWall1> wallList = tabWallDTO.getWallList();
            tabWall1Mapper.insertList(wallList);
            map.put("成功条数",cgNum);
            map.put("失败数据",listFailed);

        } catch (Exception e) {
            e.printStackTrace();
            //TODO 删除相应的数据
            if(null != serviceId) {
                tabDataSettingMapper.delTabDataSetting(serviceId);
                tabDataSettingMapper.delTabService(serviceId);
                tabDataSettingMapper.delUserService(serviceId);
            }
            return result.failure(500, "系统错误");
        }

        result.success(map);
        return result;
    }


    private void waitTaskListCompleted(List<Future<?>> list) throws InterruptedException {
        int finash;
        do {
            finash = 0;
            for (Future<?> future : list) {
                if (future.isDone()) {
                    finash++;
                }
            }
            Thread.sleep(100);
        } while (finash < list.size());
    }
}
